home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / lalr.lha / lalr / src / Check.mi < prev    next >
Text File  |  1992-08-18  |  13KB  |  464 lines

  1. (* check and repair inconsitences *)
  2.  
  3. (* $Id: Check.mi,v 2.4 1992/08/07 15:22:49 grosch rel $ *)
  4.  
  5. (* $Log: Check.mi,v $
  6.  * Revision 2.4  1992/08/07  15:22:49  grosch
  7.  * allow several scanner and parsers; extend module Errors
  8.  *
  9.  * Revision 2.3  1992/02/05  08:00:15  grosch
  10.  * renamed NULL to DevNull
  11.  *
  12.  * Revision 2.2  1991/11/21  14:53:14  grosch
  13.  * new version of RCS on SPARC
  14.  *
  15.  * Revision 2.1  91/03/19  14:19:23  grosch
  16.  * fixed: IF Verbose THEN WriteClose (dFile); END;
  17.  * 
  18.  * Revision 2.0  91/03/08  18:31:37  grosch
  19.  * turned tables into initialized arrays (in C)
  20.  * moved mapping tokens -> strings from Errors to Parser
  21.  * changed interface for source position
  22.  * 
  23.  * Revision 1.5  91/01/18  20:32:43  grosch
  24.  * fixed resolution of reduce-reduce conflicts
  25.  * 
  26.  * Revision 1.4  90/06/12  16:53:43  grosch
  27.  * renamed main program to lalr, added { } for actions, layout improvements
  28.  * 
  29.  * Revision 1.3     89/05/02  14:34:18  vielsack
  30.  * new option: -v (verbose)
  31.  * 
  32.  * Revision 1.2     89/01/02  16:17:34  vielsack
  33.  * fixed bug (instead of a reduce reduce conflict a read reduce conflict
  34.  * was reported)
  35.  * 
  36.  * Revision 1.1     88/11/08  12:09:28  vielsack
  37.  * report all read items in the conclusion (not only the representative)
  38.  * 
  39.  * Revision 1.0     88/10/04  14:35:55  vielsack
  40.  * Initial revision
  41.  * 
  42.  *)
  43.  
  44. IMPLEMENTATION MODULE Check;
  45.  
  46. FROM Automaton    IMPORT Infinite, tAss, tRep, tIndex, tProduction, ProdArrayPtr,
  47.             tStateIndex, StateArrayPtr, StateIndex, tItemIndex,
  48.             ItemArrayPtr, OperArray;
  49. FROM Debug    IMPORT dFile, tConflict, DebugHead, DebugState, DebugEnd, InformIgnored,
  50.             InformLowPri, InformRightAss, InformLeftAss, InformKept,
  51.             InformConflict, NewLine;
  52. FROM Errors    IMPORT eInternal, eInformation, eWarning, eError, eFatal, eString,
  53.             eShort, eTermSet, ErrorMessageI;
  54. FROM Idents    IMPORT tIdent;
  55. FROM IO        IMPORT WriteOpen, WriteClose;
  56. FROM Sets    IMPORT tSet, IsElement, IsEmpty, Include, Exclude, Extract, Union,
  57.             Intersection, Assign,  AssignEmpty, MakeSet, ReleaseSet;
  58. FROM Strings    IMPORT tString, ArrayToString;
  59. FROM SysError    IMPORT StatIsBad, SysErrorMessageI;
  60. FROM SYSTEM    IMPORT ADR;
  61. FROM Positions    IMPORT NoPosition;
  62. FROM TokenTab    IMPORT MAXTerm, Terminal, Prio, TokenToSymbol, TokenError;
  63.  
  64.   CONST
  65.     eState        = 70;
  66.     eReadRed        = 71;
  67.     eRedRed        = 72;
  68.     eReadRedRed        = 73;
  69.     eRepReadRed        = 74;
  70.     eRepRedRed        = 75;
  71.     eRepReadRedRed    = 76;
  72.     eARepReadRed    = 77;
  73.     eARepRedRed        = 78;
  74.     eARepReadRedRed    = 79;
  75.  
  76.     DevNull    = '/dev/null';
  77.     DEBUG    = '_Debug';
  78.  
  79.   PROCEDURE CheckForConflicts (VAR ok: BOOLEAN);
  80.  
  81.   (* Pruefe ob die Zustaende Konflikte beinhalten,
  82.      so weit moeglich werden Konflikte mit Hilfe von
  83.      Prioritaeten und Assoziativitaeten geloest,
  84.      falls keine Korektur moeglich ist wird das Programm mit 
  85.      einer Fehlermeldung beendet, sonst steht ein konfliktfreier
  86.      Automat zur Auswertung zur Verfuegung *)
  87.  
  88.     VAR
  89.       SymbolSet,
  90.       ConflictSet,
  91.       TempSet  : tSet;
  92.       state, 
  93.       maxState : tStateIndex;
  94.       item     : tItemIndex;
  95.       Error    : BOOLEAN;
  96.       string   : tString;
  97.     BEGIN
  98.       Error := FALSE;
  99.       MakeSet (SymbolSet,MAXTerm);
  100.       MakeSet (ConflictSet,MAXTerm);
  101.       MakeSet (TempSet,MAXTerm);
  102.  
  103.       IF Verbose THEN
  104.     dFile := WriteOpen (DEBUG);
  105.     IF StatIsBad (dFile) THEN
  106.       ArrayToString (DEBUG, string);
  107.       SysErrorMessageI (dFile, eError, eString, ADR (string));
  108.       dFile := WriteOpen (DevNull);
  109.       IF StatIsBad (dFile) THEN
  110.         ArrayToString (DevNull, string);
  111.         SysErrorMessageI (dFile, eFatal, eString, ADR (string));
  112.       END;
  113.     END;
  114.       END;
  115.  
  116.       (* fuer Debug wird in Number ein Verweis auf den zugeh. State eingetragen *)
  117.  
  118.       maxState := StateIndex;
  119.       FOR state := 1 TO maxState DO
  120.     WITH StateArrayPtr^[state] DO
  121.       FOR item := Items TO Items + Size - 1 DO
  122.         WITH ItemArrayPtr^[item] DO
  123.           Number := state;
  124.         END;
  125.       END;
  126.     END;
  127.       END;
  128.  
  129.       FOR state := 1 TO maxState DO
  130.     WITH StateArrayPtr^[state] DO
  131.  
  132.       AssignEmpty (ConflictSet);
  133.       AssignEmpty (SymbolSet);
  134.  
  135.       FOR item := Items TO Items + Size - 1 DO
  136.         WITH ItemArrayPtr^[item] DO
  137.           CASE Rep OF
  138.           | TermRep :
  139.           IF IsElement (Read,SymbolSet) THEN
  140.             Include (ConflictSet,Read);
  141.           ELSE
  142.             Include (SymbolSet,Read);
  143.           END;
  144.           | RedRep :
  145.           Assign (TempSet,Set);
  146.           Intersection (TempSet,SymbolSet);
  147.           Union (ConflictSet,TempSet);
  148.           Union (SymbolSet,Set);
  149.           ELSE
  150.           END;
  151.         END;
  152.       END;
  153.  
  154.       IF NOT IsEmpty (ConflictSet) THEN
  155.         RepairConflict (state, ConflictSet);
  156.         IF NOT IsEmpty (ConflictSet) THEN Error := TRUE; END;
  157.       END;
  158.     END;
  159.       END;
  160.  
  161.       ReleaseSet (TempSet);
  162.       ReleaseSet (ConflictSet);
  163.       ReleaseSet (SymbolSet);
  164.       ok := NOT Error;
  165.       IF Verbose THEN
  166.         WriteClose (dFile);
  167.       END;
  168.     END CheckForConflicts;
  169.  
  170. PROCEDURE RepairConflict (state: tStateIndex; VAR ConflictSet: tSet);
  171.     VAR
  172.       todo                        : tSet;
  173.       LookAhead                        : Terminal;
  174.       ReadRedSet, RedRedSet, ReadRedRedSet, RepReadRedSet,
  175.       RepRedRedSet, RepReadRedRedSet, ARepReadRedSet,
  176.       ARepRedRedSet, ARepReadRedRedSet            : tSet;
  177.       Priority, ReducePri, ShiftPri            : Prio;
  178.       Associativity, ReduceAss, ShiftAss        : tAss;
  179.       MinProdNo                        : tIndex;
  180.       OnlyOpers                        : BOOLEAN;
  181.       ReduceCount, ShiftCount, ReduceRest, ShiftRest    : CARDINAL;
  182.       item                        : tItemIndex;
  183.       prod                        : tProduction;
  184.       ConflictFree                    : BOOLEAN;
  185.     BEGIN
  186.       MakeSet (ReadRedSet, MAXTerm);
  187.       MakeSet (RedRedSet, MAXTerm);
  188.       MakeSet (ReadRedRedSet, MAXTerm);
  189.       MakeSet (RepReadRedSet, MAXTerm);
  190.       MakeSet (RepRedRedSet, MAXTerm);
  191.       MakeSet (RepReadRedRedSet, MAXTerm);
  192.       MakeSet (ARepReadRedSet, MAXTerm);
  193.       MakeSet (ARepRedRedSet, MAXTerm);
  194.       MakeSet (ARepReadRedRedSet, MAXTerm);
  195.  
  196.       IF Verbose THEN
  197.     DebugHead (state);
  198.     DebugState (state, ConflictSet);
  199.       END;
  200.  
  201.       MakeSet (todo, MAXTerm);
  202.       Assign (todo, ConflictSet);
  203.  
  204.       WITH StateArrayPtr^[state] DO
  205.     WHILE NOT IsEmpty (todo) DO
  206.       LookAhead := Extract (todo);
  207.  
  208.       OnlyOpers := TRUE;
  209.       ReduceCount := 0;
  210.       ShiftCount := 0;
  211.       ReduceRest := 0;
  212.       ShiftRest := 0;
  213.       ReducePri := 0;
  214.       ReduceAss := none;
  215.       ShiftPri  := 0;
  216.       ShiftAss  := none;
  217.       MinProdNo := 10000;
  218.  
  219.       FOR item := Items TO Items + Size - 1 DO
  220.         WITH ItemArrayPtr^[item] DO
  221.           IF (Rep = RedRep) AND IsElement (LookAhead, Set) THEN
  222.         INC (ReduceCount);
  223.         prod := ADR(ProdArrayPtr^[Prod]);
  224.         IF prod^.Pri = 0 THEN
  225.           OnlyOpers := FALSE;
  226.         ELSIF prod^.Pri > ReducePri THEN
  227.           ReducePri := prod^.Pri;
  228.           ReduceAss := prod^.Ass;
  229.         END;
  230.         IF prod^.ProdNo < MinProdNo THEN
  231.           MinProdNo := prod^.ProdNo;
  232.         END;
  233.           ELSIF (Rep = TermRep) AND (Read = LookAhead) THEN
  234.         INC (ShiftCount);
  235.         IF OperArray [LookAhead].Pri = 0 THEN
  236.           OnlyOpers := FALSE;
  237.         ELSE
  238.           ShiftPri := OperArray [LookAhead].Pri;
  239.           ShiftAss := OperArray [LookAhead].Ass;
  240.         END;
  241.           END;
  242.         END;
  243.       END;
  244.  
  245.       IF OnlyOpers THEN
  246.  
  247.         IF ReducePri > ShiftPri THEN
  248.           Priority        := ReducePri;
  249.           Associativity    := ReduceAss;
  250.         ELSE
  251.           Priority        := ShiftPri;
  252.           Associativity    := ShiftAss;
  253.         END;
  254.         
  255.         FOR item := Items TO Items + Size - 1 DO
  256.           WITH ItemArrayPtr^[item] DO
  257.         IF (Rep = RedRep) AND IsElement (LookAhead, Set) THEN
  258.           prod := ADR (ProdArrayPtr^[Prod]);
  259.           IF (prod^.Pri < Priority) THEN    (* lower priority    *)
  260.             IF Verbose THEN
  261.               InformLowPri (item, LookAhead);    (* ignore reduce    *)
  262.             END;
  263.             Exclude (Set, LookAhead);
  264.             IF IsEmpty (Set) THEN Rep := NoRep; END;
  265.           ELSIF (prod^.Pri = Priority) AND    (* max. priority    *)
  266.              ((Associativity = right) OR    (* right associative    *)
  267.              (Associativity = nonassoc)) AND    (* not associative    *)
  268.              (ShiftPri = Priority) THEN        (* same priority    *)
  269.             IF Verbose THEN
  270.               InformRightAss (item, LookAhead);    (* ignore reduce    *)
  271.             END;
  272.             Exclude (Set, LookAhead);
  273.             IF IsEmpty (Set) THEN Rep := NoRep; END;
  274.           ELSE
  275.             IF Verbose THEN
  276.               InformKept (item, LookAhead);    (* keep reduce        *)
  277.             END;
  278.             INC (ReduceRest);
  279.           END;
  280.         ELSIF (Read = LookAhead) THEN
  281.           IF (ShiftPri < Priority) THEN        (* lower priority    *)
  282.             IF Verbose THEN
  283.               InformLowPri (item, LookAhead);    (* ignore read        *)
  284.             END;
  285.             Rep := NoRep;
  286.           ELSIF (ShiftPri = Priority) AND    (* max. priority    *)
  287.              ((Associativity = left) OR        (* left associative    *)
  288.              (Associativity = nonassoc)) AND    (* not associative    *)
  289.              (ReducePri = Priority) THEN    (* same priority    *)
  290.             IF Verbose THEN
  291.               InformLeftAss (item, LookAhead);    (* ignore read        *)
  292.             END;
  293.             Rep := NoRep;
  294.           ELSE
  295.             IF Verbose THEN
  296.               InformKept (item, LookAhead);    (* keep read        *);
  297.             END;
  298.             INC (ShiftRest);
  299.           END;
  300.         END;
  301.           END;
  302.         END;
  303.  
  304.       ELSE (* NOT OnlyOpers *)
  305.  
  306.         IF ShiftCount > 0 THEN    (* shift wird reduce vorgezogen *)
  307.  
  308.           FOR item := Items TO Items + Size - 1 DO
  309.         WITH ItemArrayPtr^[item] DO
  310.           IF (Rep = RedRep) AND (IsElement (LookAhead, Set)) THEN
  311.             IF Verbose THEN
  312.               InformIgnored (item, LookAhead);    (* ignore reduce *)
  313.             END;
  314.             Exclude (Set, LookAhead);
  315.             IF IsEmpty (Set) THEN Rep := NoRep; END;
  316.           ELSIF (Read = LookAhead) THEN
  317.             IF Verbose THEN
  318.               InformKept (item, LookAhead);
  319.             END;
  320.             INC (ShiftRest);
  321.           END;
  322.         END;
  323.           END;
  324.  
  325.         ELSE    (* erstes reduce auswaehlen *)
  326.  
  327.           FOR item := Items TO Items + Size - 1 DO
  328.         WITH ItemArrayPtr^[item] DO
  329.           IF (Rep = RedRep) AND (IsElement (LookAhead, Set)) THEN
  330.             prod := ADR (ProdArrayPtr^[Prod]);
  331.             IF prod^.ProdNo = MinProdNo THEN
  332.               IF Verbose THEN
  333.             InformKept (item, LookAhead);        (* keep reduce *)
  334.               END;
  335.               INC (ReduceRest);
  336.             ELSE
  337.               IF Verbose THEN
  338.             InformIgnored (item, LookAhead);    (* ignore reduce *)
  339.               END;
  340.               Exclude (Set, LookAhead);
  341.               IF IsEmpty (Set) THEN Rep := NoRep; END;
  342.             END;
  343.           END;
  344.         END;
  345.           END;
  346.         END;
  347.       END;
  348.  
  349.       ConflictFree := FALSE;
  350.  
  351.       IF ReduceRest > 1 THEN
  352.         IF ShiftRest > 0 THEN
  353.           IF Verbose THEN
  354.         InformConflict (ShRedRed);
  355.           END;
  356.           Include (ReadRedRedSet, LookAhead);
  357.         ELSE
  358.           IF Verbose THEN
  359.         InformConflict (RedRed);
  360.           END;
  361.           Include (RedRedSet, LookAhead);
  362.         END;
  363.       ELSIF ReduceRest = 1 THEN
  364.         IF ShiftRest > 0 THEN
  365.           IF Verbose THEN
  366.         InformConflict (ShRed);
  367.           END;
  368.           Include (ReadRedSet, LookAhead);
  369.         ELSE (* reduce - no conflict *)
  370.           ConflictFree := TRUE;
  371.         END;
  372.       ELSE (* ReduceRest = 0 *)
  373.         ConflictFree := TRUE;
  374.       END;
  375.  
  376.       IF Verbose THEN NewLine; END;
  377.       IF ConflictFree THEN
  378.         Exclude (ConflictSet, LookAhead);
  379.  
  380.         IF ReduceCount > 1 THEN
  381.           IF ShiftCount > 0 THEN
  382.         IF OnlyOpers THEN
  383.           Include (RepReadRedRedSet, LookAhead);
  384.         ELSE
  385.           Include (ARepReadRedRedSet, LookAhead);
  386.         END;
  387.           ELSE (* ShiftCount = 0 *)
  388.         IF OnlyOpers THEN
  389.           Include (RepRedRedSet, LookAhead);
  390.         ELSE
  391.           Include (ARepRedRedSet, LookAhead);
  392.         END;
  393.           END;
  394.         ELSIF ReduceCount = 1 THEN
  395.           IF ShiftCount > 0 THEN
  396.         IF OnlyOpers THEN
  397.           Include (RepReadRedSet, LookAhead);
  398.         ELSE
  399.           Include (ARepReadRedSet, LookAhead);
  400.         END;
  401.           ELSE (* ShiftCount = 0 *)
  402.         ERROR ('Check.RepairConflict: No Conflict (1)');
  403.           END;
  404.         ELSE (* ReduceCount = 0 *)
  405.           ERROR ('Check.RepairConflict: No Conflict (2)');
  406.         END;
  407.       END;
  408.     END;
  409.       END;
  410.  
  411.       ErrorMessageI (eState, eInformation, NoPosition, eShort, ADR (state));
  412.  
  413.       IF NOT IsEmpty (ReadRedSet) THEN
  414.     ErrorMessageI (eReadRed, eError, NoPosition, eTermSet, ADR (ReadRedSet));
  415.       END;
  416.       IF NOT IsEmpty (RedRedSet) THEN
  417.     ErrorMessageI (eRedRed, eError, NoPosition, eTermSet, ADR (RedRedSet));
  418.       END;
  419.       IF NOT IsEmpty (ReadRedRedSet) THEN
  420.     ErrorMessageI (eReadRedRed, eError, NoPosition, eTermSet, ADR (ReadRedRedSet));
  421.       END;
  422.       IF NOT IsEmpty (RepReadRedSet) THEN
  423.     ErrorMessageI (eRepReadRed, eInformation, NoPosition, eTermSet, ADR (RepReadRedSet));
  424.       END;
  425.       IF NOT IsEmpty (RepRedRedSet) THEN
  426.     ErrorMessageI (eRepRedRed, eInformation, NoPosition, eTermSet, ADR(RepRedRedSet));
  427.       END;
  428.       IF NOT IsEmpty (RepReadRedRedSet) THEN
  429.     ErrorMessageI (eRepReadRedRed, eInformation, NoPosition, eTermSet, ADR(RepReadRedRedSet));
  430.       END;
  431.       IF NOT IsEmpty (ARepReadRedSet) THEN
  432.     ErrorMessageI (eARepReadRed, eWarning, NoPosition, eTermSet, ADR(ARepReadRedSet));
  433.       END;
  434.       IF NOT IsEmpty (ARepRedRedSet) THEN
  435.     ErrorMessageI (eARepRedRed, eWarning, NoPosition, eTermSet, ADR(ARepRedRedSet));
  436.       END;
  437.       IF NOT IsEmpty (ARepReadRedRedSet) THEN
  438.     ErrorMessageI (eARepReadRedRed, eWarning, NoPosition, eTermSet, ADR(ARepReadRedRedSet));
  439.       END;
  440.  
  441.       ReleaseSet (ReadRedSet);
  442.       ReleaseSet (RedRedSet);
  443.       ReleaseSet (ReadRedRedSet);
  444.       ReleaseSet (RepReadRedSet);
  445.       ReleaseSet (RepRedRedSet);
  446.       ReleaseSet (RepReadRedRedSet);
  447.       ReleaseSet (ARepReadRedSet);
  448.       ReleaseSet (ARepRedRedSet);
  449.       ReleaseSet (ARepReadRedRedSet);
  450.       ReleaseSet (todo);
  451.       IF Verbose THEN DebugEnd; END;
  452.     END RepairConflict;
  453.  
  454.   PROCEDURE ERROR (a: ARRAY OF CHAR);
  455.     VAR s: tString;
  456.     BEGIN
  457.       ArrayToString (a, s);
  458.       ErrorMessageI (eInternal, eFatal, NoPosition, eString, ADR (s));
  459.     END ERROR;
  460.  
  461. BEGIN
  462.   Verbose := FALSE;
  463. END Check.
  464.